using System;
using System.Collections.Generic;
using System.Windows.Forms;
using OhioState.AssetManaged;
using OhioState.Graphics.Proxy;

namespace OhioStateVolumeRenderer
{
    public class Deformation
    {
        private static Deformation instance;
        private MouseEventHandler mouseHandler;
        private MouseEventHandler mouseClickHandler;
        private System.Windows.Forms.Control target;
        private bool isShaderLinked = false;
        private ShaderProgram deformShader;
        private OSUVolume osuVolume;
        private MaterialProxy currentMaterial;
         private double mx1, mx2, my1, my2, mx3, my3, mx4, my4;
        //private float lensRadius;
        //private float zoomLevel;

        public static Deformation Instance
        {
            get
            {
                if(instance == null)
                    instance = new Deformation();
                return instance;
            }
            set
            {
                if (instance == null)
                    instance = value;
            }
        }

        private Deformation()
        {
            mx1 = mx2 = my1 = my2 = 0;
        }

        public void SetModeActive(System.Windows.Forms.Control targetControl, OSUVolume osuVol)
        {
            target = targetControl;
            osuVolume = osuVol;
            if (mouseHandler == null)
            {
                mouseHandler = new MouseEventHandler(MouseMovHandler);
            }
            if(mouseClickHandler == null)
            {
                mouseClickHandler += new MouseEventHandler(MouseClickHandler);
            }
            target.MouseMove += mouseHandler;
            target.MouseClick += mouseClickHandler;

            if (!isShaderLinked)
            {
                LinkTheShader();
                isShaderLinked = true;
            }
            target.Invalidate();
        }

        public void SetModeInactive()
        {
            if (mouseHandler != null)
            {
                target.MouseMove -= mouseHandler;    
            }

            if (mouseClickHandler != null)
            {
                target.MouseClick -= mouseClickHandler;
            }


            target.Invalidate();
        }

        private void MouseClickHandler(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            double controlWidth = ((System.Windows.Forms.Control)sender).Width;
            double controlHeight = ((System.Windows.Forms.Control)sender).Height;

            double resultX = (double)e.X / controlWidth;
            double resultY = (controlHeight - e.Y) / controlHeight;

            if (currentMaterial == null)//nothing is selected in the combobox
                return;

            if (currentMaterial.Shader != deformShader)
            {
                currentMaterial.Shader = deformShader;
            }
            mx1=mx2;
            my1=my2;
            mx2 = mx3;
            my2 = my3;
            mx3 = mx4;
            my3 = my4;
            mx4 = resultX;
            my4 = resultY;

            Dictionary<string, UniformVariableValues> uv = currentMaterial.UniformVariableValues;

            foreach (KeyValuePair<String, UniformVariableValues> kvp in uv)
            {
                UniformVariableValues val = kvp.Value;
                
                if (kvp.Key.Equals("mouseXClick"))
                {
                    val[0].Float = new SharedFloat((float)mx1);
                                    }
                
                if (kvp.Key.Equals("mouseX2Click"))
                {
                    val[0].Float = new SharedFloat((float)mx2);
                }
                if (kvp.Key.Equals("mouseX3Click"))
                {
                    val[0].Float = new SharedFloat((float)mx1);
                }

                if (kvp.Key.Equals("mouseX4Click"))
                {
                    val[0].Float = new SharedFloat((float)mx2);
                }
          
                if (kvp.Key.Equals("mouseYClick"))
                {
                    val[0].Float = new SharedFloat((float)my1);
                }
                

                if (kvp.Key.Equals("mouseY2Click"))
                {
                    val[0].Float = new SharedFloat((float)my2);
                }
                if (kvp.Key.Equals("mouseY3Click"))
                {
                    val[0].Float = new SharedFloat((float)my1);
                }

                if (kvp.Key.Equals("mouseY4Click"))
                {
                    val[0].Float = new SharedFloat((float)my2);
                }             
            }
                            
            target.Invalidate();
        }
        private void MouseMovHandler(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            double controlWidth = ((System.Windows.Forms.Control)sender).Width;
            double controlHeight = ((System.Windows.Forms.Control)sender).Height;

            double resultX = (double)e.X / controlWidth;
            double resultY = (controlHeight - e.Y)/controlHeight;

            if (currentMaterial == null)//nothing is selected in the combobox
                return;

            if (currentMaterial.Shader != deformShader)
            {
                currentMaterial.Shader = deformShader;
            }

            Dictionary<string, UniformVariableValues> uv = currentMaterial.UniformVariableValues;

            foreach (KeyValuePair<String, UniformVariableValues> kvp in uv)
            {
                UniformVariableValues val = kvp.Value;
                if (kvp.Key.Equals("mouseX"))
                {
                    val[0].Float = new SharedFloat((float)resultX);
                }
                else if (kvp.Key.Equals("mouseY"))
                {
                    val[0].Float = new SharedFloat((float)resultY);
                }
                //else if(lensRadius == 0 && kvp.Key.Equals("lensRadius"))//if radius hasn't been set yet
                //{
                //    val[0].Float = new SharedFloat((float)0.14f);
                //}
                //else if (zoomLevel == 0 && kvp.Key.Equals("zoomLevel"))//if zoom level hasn't been set yet
                //{
                //    val[0].Float = new SharedFloat((float)0.14f);
                //}
            }

            target.Invalidate();
        }

        private void LinkTheShader()
        {
            List<FragmentShader> fragList = new List<FragmentShader>(1);
            List<VertexShader> vertList = new List<VertexShader>(1);

            VertexShader vert = AssetManager.Instance.Find(typeof(VertexShader), "deform") as VertexShader;
            FragmentShader frag = AssetManager.Instance.Find(typeof(FragmentShader), "deform") as FragmentShader;

            vertList.Add(vert);
            fragList.Add(frag);

            deformShader = new ShaderProgram("Deform Shader", vertList, fragList);
            //GLShader.Instance.Link(deformShader);

            AssetManager.Instance.Add(deformShader);
        }

        public void setCurrentMaterial(MaterialProxy material)
        {
            currentMaterial = material;
            if (currentMaterial.Shader != deformShader)
            {
                currentMaterial.Shader = deformShader;
            }
        }

        //public void SetLensRadius(float radius)
        //{
        //    this.lensRadius = radius;
        //    if (currentMaterial == null) return;

        //    Dictionary<string, UniformVariableValues> uv = currentMaterial.UniformVariableValues;
        //    foreach (KeyValuePair<String, UniformVariableValues> kvp in uv)
        //    {
        //        UniformVariableValues val = kvp.Value;
        //        if (kvp.Key.Equals("lensRadius"))
        //        {
        //            val[0].Float = new SharedFloat((float)lensRadius);
        //        }
        //    }
        //}

        //public void SetZoomLevel(float zoomLevel)
        //{
        //    this.zoomLevel = zoomLevel;
        //    if (currentMaterial == null) return;

        //    Dictionary<string, UniformVariableValues> uv = currentMaterial.UniformVariableValues;
        //    foreach (KeyValuePair<String, UniformVariableValues> kvp in uv)
        //    {
        //        UniformVariableValues val = kvp.Value;
        //        if (kvp.Key.Equals("zoomLevel"))
        //        {
        //            val[0].Float = new SharedFloat((float)zoomLevel);
        //        }
        //    }
        //}
    }
}
